﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace Lesson19
{
    // 迭代器

    #region 迭代器
    // 迭代器是什么
    // 迭代器（iterator）有时又称光标（cursor）
    // 是程序设计的软件设计模型
    // 迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素 而又 不暴露其内部标识
    // 从表现上看：是可以在容器对象（例如链表或数组）上遍历访问的接口，设计人员无需关心容器对象的内存分配的实现细节
    // 可以用foreach遍历的类，都是实现了迭代器的


    // 标准迭代器的实现方法
    // 关键接口： IEnumerator, IEnumerable 两个
    // 命名空间： using System.Collections
    // 可以通过同时继承IEnumerator和IEnumerable实现其中的方法

    class CustomList : IEnumerable, IEnumerator
    {
        private int[] list;

        // 当前迭代器的索引，光标
        private int index = -1;  // -1表示光标在第一个元素之前

        public CustomList()
        {
            list = new int[] { 1,2,3,4,5,6,7,8,9 };

        }

        // 继承IEnumerable 实现的一个方法

        public IEnumerator GetEnumerator()
        {
            return this; // 继承了IEnumerable,直接返回当前对象本身
        }

        // 继承IEnumerator 实现的
        //public object Current => list[index];  // 可以直接简写
        public object Current 
        { 
            get
            {
                return list[index]; // 返回当前光标指向的元素
            }
        }

        public bool MoveNext()
        {
            ++index;  // 首先自加1，让光标指向第一个位置
            return index < list.Length;
        }

        public void Reset()
        {
            index = -1;   // 重置光标位置
        }
    }


    // 用 yield return  语法糖实现迭代器
    // yield return 是c#提供的语法糖
    // 主要作用就是将复杂逻辑简单化，可以增加程序的可读性
    // 关键接口 IEnumerable
    // 命名空间： using System.Collections
    //  让想要通过foreach遍历的类实现接口中的方法GetEnumerator

    class CustomList2 : IEnumerable
    {
        private int[] list;

        public CustomList2()
        {
            list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        }

        public IEnumerator GetEnumerator()
        {
            // 直接使用yield return语法糖
            for (int i = 0; i < list.Length; i++)
            {
                yield return list[i]; // 返回当前光标指向的元素
            }
        }
    }

    // 用 yield return  语法糖为泛型类实现迭代器
    class CustomList<T> : IEnumerable
    {
        private T[] array;

        public CustomList(params T[] array)
        {
            this.array = array;
        }

        public IEnumerator GetEnumerator()
        {
            // 直接使用yield return语法糖
            for (int i = 0; i < array.Length; i++)
            {
                yield return array[i]; // 返回当前光标指向的元素
            }
        }
    }

    #endregion

    internal class Program
    {
        static void Main(string[] args)
        {

            CustomList list = new CustomList();

            // foreach本质：
            // 1、会先去找 in 后面的 对象 IEnumerator， 会调用其中的GetEnumerator方法 来获取
            // 2、执行得到这个 IEnumerator 对象中的 MoveNext 方法
            // 3、只要MoveNext方法的返回值为true就会去得到Current，然后赋值给item
            foreach (int item in list)  // CustomList类实现了IEnumerable接口后不报错了, 或者说实现了GetEnumerator方法
            {
                Console.WriteLine(item);
            }

            CustomList2 list2 = new CustomList2();

            foreach (int item in list2)  
            {
                Console.WriteLine(item);
            }


            CustomList<string> list3 = new CustomList<string>(new string[] { "111", "2", "88" });

            foreach (string item in list3)
            {
                Console.WriteLine(item);
            }
        }
    }
}
